package drds.server.net.handler;

import java.nio.ByteBuffer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import drds.server.Server;
import drds.server.config.ErrorCode;
import drds.server.net.Handler;
import drds.server.net.SessionContextGroupShareResources;
import drds.server.net.packet.Packet;
import drds.server.net.packet.QuitPacket;
import drds.server.net.packet.auth.AuthRequestPacket;
import drds.server.server.SessionContext;

/**
 * 
 * @author 曹正辉<330937205@qq.com>
 * 
 */
public class AuthHandler implements Handler {

	private static final Logger LOGGER = LoggerFactory.getLogger(AuthHandler.class);
	private static final byte[] AUTH_OK = new byte[] { 7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0 };

	protected final SessionContext sessionContext;

	public AuthHandler(SessionContext sessionContext) {
		this.sessionContext = sessionContext;
	}

	@Override
	public void handle(byte[] bytes) {
		// check quit packet
		if (bytes.length == QuitPacket.QUIT.length && //
				bytes[4] == Packet.QUIT) {//
			/**
			 * 在此sessionContext只需要返回退出成功命令,客户端端口连接，之后进行的资源清理由DRDS容器进行清理。这样性能高一点。
			 */
			sessionContext.close("quit packet");
			return;
		}

		AuthRequestPacket authPacket = new AuthRequestPacket();
		authPacket.read(bytes);

		/** database name is right */
		if (!checkSchema(authPacket.database)) {
			fail(ErrorCode.ERROR_DATABASE_ERROR, "unknown database:" + authPacket.database + "");
			return;
		}
		/** username is exists and allowed for visiting drds */
		if (!checkUsername(authPacket.userName)) {
			String s = "access denied for user:" + authPacket.userName + "' to database:" + authPacket.database + "";
			fail(ErrorCode.ERROR_DENIED_FOR_USER_DATABASE_ERROR, s);
			return;
		}
		/** database name is right */
		if (!checkPassword(authPacket.userName, authPacket.password)) {
			fail(ErrorCode.ERROR_DENIED_FOR_USER_DATABASE_ERROR, "access denied for user '" + authPacket.userName + "':password is error ");
			return;
		}
		/** database name is right */
		if (isDegrade(authPacket.userName)) {
			fail(ErrorCode.ERROR_DENIED_FOR_USER_DATABASE_ERROR, "access denied for user '" + authPacket.userName + "': service be degraded ");
			return;
		}
		success(authPacket);
	}

	private boolean checkUsername(String username) {
		return false;
	}

	private boolean checkPassword(String username, byte[] password) {
		return false;
	}

	/**
	 * 和当前的DRDS容器进行核对,虚拟的数据库实例名是否一致。
	 */
	private boolean checkSchema(String database) {
		return true;
	}

	// 前端 connection 达到该用户设定的阀值后, 立马降级拒绝连接
	protected boolean isDegrade(String user) {

		int benchmark = 0;
		int all = 0;
		SessionContextGroupShareResources[] sessionContextGroupShareResourcess = Server.getInstance().getSessionContextGroupShareResources();
		for (SessionContextGroupShareResources sessionContextGroupShareResources : sessionContextGroupShareResourcess) {
			all += sessionContextGroupShareResources.getSessionContextMap().size();
		}

		if (all >= benchmark) {
			return true;
		}
		return false;
	}

	protected void success(AuthRequestPacket auth) {
		sessionContext.setHandler(new CommandHandler(sessionContext));

		ByteBuffer byteBuffer = sessionContext.allocate();
		sessionContext.write(sessionContext.writeToByteBuffer(AUTH_OK, byteBuffer));
	}

	protected void fail(int errno, String info) {
		sessionContext.writeErrorMessage((byte) 2, errno, info);
		LOGGER.error(sessionContext.toString() + info);
	}

}